﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;

using Microsoft.WindowsAzure.StorageClient;
using AzureGames.Model;
using AzureGames.Model.Statistics;

using AutoMapper;
using AzureGames.Data.Implementation.ServiceEntities;

namespace AzureGames.Data.Implementation
{
    public class GameStatisticsRepository : AzureTableRepository<GameStatisticsEntity>, IGameStatisticsRepository
    {
        const string PARTITIONKEY = "GameStatistics";
       public GameStatisticsRepository() : base("GameStatistics") 
       {
           AutoMapper.Mapper.CreateMap<Model.Statistics.GameStatistics, ServiceEntities.GameStatisticsEntity>()
              .ForMember(m => m.PartitionKey, s => s.UseValue(PARTITIONKEY))
              .ForMember(m => m.RowKey, s => s.MapFrom(g => BuildKey(g.GameDefinitionID, g.CreatedDate, g.GameType)));

           AutoMapper.Mapper.CreateMap<ServiceEntities.GameStatisticsEntity, Model.Statistics.GameStatistics>();
       }


       

        private string BuildKey(int gameDefinitionID, DateTime date, GameType gameType)
        {
            return string.Format("{0}:{1}:{2}", gameDefinitionID, date.ToString("yyyyMMdd"), gameType);
        }

        private DateTime GetDateMaxRange(RANGE range)
        {
            switch (range)
            {
                default:
                case RANGE.Today:
                    return DateTime.Now.Date;
                case RANGE.ThisWeek:
                    return DateTime.Now.Date.AddDays(-7);
                case RANGE.ThisYear:
                    return DateTime.Now.Date.AddYears(-1);
                case RANGE.ThisMonth:
                    return DateTime.Now.Date.AddMonths(-1);
            }
        }
        

        public void AddGameStatistic(int gameDefinitionID, GameType gameType, DateTime date, int state)
        {
            var current = Get(PARTITIONKEY, BuildKey(gameDefinitionID, date, gameType));

            if (current == null)
                Add(new GameStatisticsEntity
                {
                    CancelledGames = state == Board.Cancelled ? 1 : 0,
                    CompletedGames = state == Board.Completed ? 1 : 0,
                    CreatedGames = state == Board.Created ? 1 : 0,
                    Date = date.Date,
                    CreatedDate = DateTime.Now,
                    GameDefinitionID = gameDefinitionID,
                    GameType = (int)gameType,
                    PartitionKey = PARTITIONKEY,
                   RowKey = BuildKey(gameDefinitionID, date, gameType)
                });
            else
            {
                switch (state)
                {
                    case Board.Completed:
                        current.CompletedGames += 1;
                        break;
                    case Board.Created:
                        current.CreatedGames += 1;
                        break;
                    case Board.Cancelled:
                        current.CancelledGames += 1;
                        break;
                }

                Update(current);
            }
        }

        public void RemoveGameStatistic(int gameDefinitionID, GameType gameType, DateTime date, int state)
        {
            var current = Get(PARTITIONKEY, BuildKey(gameDefinitionID, date, gameType));

            if (current == null)
                Add(new GameStatisticsEntity
                {
                    CancelledGames = 0,
                    CompletedGames = 0,
                    CreatedGames = 0,
                    Date = date.Date,
                    CreatedDate = DateTime.Now,
                    GameDefinitionID = gameDefinitionID,
                    GameType = (int)gameType,
                    PartitionKey = PARTITIONKEY,
                    RowKey = BuildKey(gameDefinitionID, date, gameType)
                });
            else
            {
                switch (state)
                {
                    case Board.Completed:
                        current.CompletedGames -= 1;
                        break;
                    case Board.Created:
                        current.CreatedGames -= 1;
                        break;
                    case Board.Cancelled:
                        current.CancelledGames -= 1;
                        break;
                }

                Update(current);
            }
        }

        public List<GameStatistics> GetGameStatistics(int gameDefinitionID, RANGE range)
        {
            DateTime fromDate = GetDateMaxRange(range);

            var stats = dataContext.CreateQuery<GameStatisticsEntity>(this.tableName)
                .Where(n => n.PartitionKey == PARTITIONKEY && n.GameDefinitionID == gameDefinitionID && n.Date >= fromDate);

            // TODO: figure out why casting is failing
            // return stats.Cast<Model.Statistics.GameStatistics>().ToList();                        
            List<GameStatistics> gameStatistics = new List<GameStatistics>();

            foreach (var entity in stats)
                gameStatistics.Add(entity);

            return gameStatistics;
        }
    }
}
